#ifndef THREAD_H_
#define THREAD_H_

#include "base/closure.h"
#include "base/macro_def.h"
#include "base/scoped_ptr.h"

#include <pthread.h>

class Thread {
 public:
  Thread(Closure* c)
      : tid_(-1),
        closure_(c) {
  }
  virtual ~Thread() {
    Join();
  }

  bool Start() {
    if (tid_ != -1)
      return false;
    int32 ret = ::pthread_create(&tid_, NULL, &Thread::Run,
                                 (void*) closure_.get());
    if (ret != 0) {
      PLOG(WARNING) << "pthread_create error";
    }
    return ret == 0;
  }

  void Join() {
    if (tid_ == -1)
      return;
    ::pthread_join(tid_, NULL);
    tid_ = -1;
  }

 private:
  pthread_t tid_;
  scoped_ptr<Closure> closure_;

  static inline void* Run(void* data);

  DISALLOW_COPY_AND_ASSIGN(Thread);
};

class StoppableThread : public Thread {
 public:
  StoppableThread(Closure* c)
      : Thread(closure_ = new StoppableClosure(c)) {
  }

  void Join() {
    closure_->Stop();
    Thread::Join();
  }

 private:
  StoppableClosure* closure_;

  DISALLOW_COPY_AND_ASSIGN(StoppableThread);
};

inline void* Thread::Run(void* data) {
  Closure*c = (Closure*) data;
  c->Run();
  return NULL;
}

#endif
